package org.sdnstproject.interlayer.DummyProxyV13;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;

import org.projectfloodlight.openflow.exceptions.OFParseError;
import org.projectfloodlight.openflow.protocol.OFFactories;
import org.projectfloodlight.openflow.protocol.OFHello;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFMessageReader;
import org.projectfloodlight.openflow.protocol.OFType;
import org.sdnstproject.interlayer.interlayerProxy.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

public class ListenV13 extends Thread{
	private static final Logger log = LoggerFactory.getLogger(ListenV13.class);
	private Configuration config = Configuration.getInstance();
	private int port = Integer.parseInt(config.getInterlayerPort());
	public ServerSocket serverSock;
	public volatile boolean running = true;
	public InputStream in;
	public OutputStream out;
	private DummyControllerV13 ofController;
	private OFMessageReader<OFMessage> reader = OFFactories.getGenericReader();
	public volatile boolean first = true;
	
	public ListenV13(DummyControllerV13 ofController) {
		this.ofController = ofController;
	}
	public void getServerSocket() throws IOException {
		log.info("[DummyController] Listening switches on " + port);
        serverSock = new ServerSocket(port);
        serverSock.setReuseAddress(true);
	}
	@Override
	public void run() {
		try {
			log.info("[DummyController] Listening switches on " + port);
	        serverSock = new ServerSocket(port);
	        serverSock.setReuseAddress(true);
		} catch (IOException e1) {
			running = false;
			e1.printStackTrace();
		}
		try {
			while(running && !Thread.currentThread().isInterrupted()) {
				Socket tempSocket = null;
				tempSocket = serverSock.accept();
				log.info("[DummyController] Switch connected from  " + tempSocket.toString());
				in = tempSocket.getInputStream();
				out = tempSocket.getOutputStream();
				
				byte[] temprecv = new byte[32];
				try {
					while (first && in.read(temprecv, 0, temprecv.length) != -1) {
						log.info("first get a massage.");
						if(temprecv[1] == (byte)0) {
							ByteBuf bb = Unpooled.copiedBuffer(temprecv);
							OFMessage message;
							try {
								message = reader.readFrom(bb);
							} catch (OFParseError e) {
								log.info(e.toString());
								continue;
							}
							if(message.getType() == OFType.HELLO) {
								log.info(message.toString());
								ofController.targetSock = tempSocket;
								ofController.in = in;
								ofController.out = out;
//								ofController.state.processOFMsg(message);
								ofController.state.processOFHello((OFHello)message);
								ofController.start();
								log.info("ofController start.");
								first = false;
								break;
							}
							bb.clear();
						}
					}
				} catch (Exception e) {
					log.info(e.toString());
					continue;
				}
			}
		} catch (SocketException e) {
			log.info(e.toString());
		}catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				if(serverSock != null) serverSock.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}
}
